/*
 ***************************************************************************
 * MediaTek Inc.
 * 4F, No. 2 Technology 5th Rd.
 * Science-based Industrial Park
 * Hsin-chu, Taiwan, R.O.C.
 *
 * (c) Copyright 1997-2015, MediaTek, Inc.
 *
 * All rights reserved. MediaTek source code is an unpublished work and the
 * use of a copyright notice does not imply otherwise. This source code
 * contains confidential trade secret material of MediaTek. Any attemp
 * or participation in deciphering, decoding, reverse engineering or in any
 * way altering the source code is stricitly prohibited, unless the prior
 * written consent of MediaTek Technology, Inc. is obtained.
 ***************************************************************************

    Module Name: reduce_tcpack.h

    Abstract:
        The corresponding defines and data structure for RACK (Reduce TCP ACK)
    engine.

    Revision History:
    Who         When            What
    Hank Huang  2015/07/13      initial version
    --------    ----------      ----------------------------------------------
*/
    
#ifndef __REDUCE_TCPACK_H__
#define __REDUCE_TCPACK_H__

#define REDUCE_ACK_MAX_HASH_BUCKETS 		2048
#define MAX_REDUCE_ACK_CNX_ENTRY			256					// 256 connections at max
#define MAX_CONSECUTIVE_DROP_CNT			5
#define MAX_CONSECUTIVE_DATA_CNT			10
#define MAX_SUPPORTED_ACK_RATIO             5                   // max ack ratio we supported
#define REDUCE_PROB_INC_TH					1
#define REDUCE_PROB_INC_STEP				20
#define REDUCE_ACK_CNX_POLLING_INTERVAL 	(10*HZ) 			// 10 seconds
#define REDUCE_ACK_POLLING_INTERVAL 		(20*HZ/1000)		// 20ms
#define REDUCE_ACK_TIMEOUT					(250*HZ/1000)		// 250ms
#define REDUCE_ACK_CNX_TIMEOUT				(180*HZ)			// 180 seconds
#define REDUCE_ACK_FIN_CNX_TIMEOUT			(10*HZ)				// 10 seconds
#define REDUCE_ACK_ONE_PERCENT				(0x80000000/100)
#define DEFAULT_REDUCE_PERCENT				(REDUCE_ACK_ONE_PERCENT * 100)
#define REDUCE_ACK_IGNORE_CNT				(126)
#define REDUCE_ACK_UINT32_MAX				4294967295U
#define REDUCE_ACK_PERCENTAGE(prob)			({ \
		UINT32 i = 0, percentage = 0;\
		for (percentage=0; percentage<100; percentage++) {\
        if (i >= prob) {\
            break;\
        }\
        else {\
            i += REDUCE_ACK_ONE_PERCENT;\
        }}percentage;})
//0813
#define REDUCE_ACK_PKT_CACHE				0

enum {
	TCP_ACK = 0,
	TCP_DATA = 1,
};

enum {
	STATE_INIT = 0,
	STATE_SS = 1,
	STATE_REDUCTION = 2,
	STATE_CONGESTION = 3,
	STATE_TERMINATION = 4,
};

enum {
	REDUCE_ACK_DISABLE = 0,
	REDUCE_ACK_ENALBE = 1,
	REDUCE_ACK_ENABLE_WITOUT_DEL_CNX = 2,
    REDUCE_ACK_ENABLE_NO_DROP_MODE = 3,    // for testing only, check algorithm CPU cost
	REDUCE_ACK_ENABLE_LAST = 3,
};

typedef struct _rack_packet{
	UINT32 sip;
	UINT32 dip;
	UINT16 sport;
	UINT16 dport;
	UINT32 type;		// TCP_ACK or TCP_DATA
	UINT32 ack;
	UINT32 seq;
	UINT32 wsize;
	UINT16 opt_len;
	UINT32 data_len;
	UINT8 wscale;
	UINT8 flags;
	UINT16 mss;
	ULONG timestamp;	// timestamp that incoming TCP packet is parsed
	UINT32 opt_have_sack;
}rack_packet;

/* Each rack_cnx may be linked to two tables:
   1. Hash table by (sip, dip, sport, dport): pAd->ackCnxHashTbl
   2. Link list for all connections for flushing purpose: pApd->ackCnxList
 */
typedef struct _rack_cnx{
	/*
	 * Parameters which retrieved from TCP data/ack packets
	 */
	struct {
		UINT32 sip;
		UINT32 dip;
		UINT16 sport;
		UINT16 dport;
	}tuple;                 // 4-tuple
	UINT32 ack;				// acknowledgement # of last ACK packet
	UINT32 seq;				// sequence # of last DATA packet
	UINT8  wscale;			// window scale (WS) parsed from TCP option of SYN packet
	UINT32 wsize;			// window size inside last ACK packet (RWND)
	UINT32 mss;				// Max Segment Size parsed from TCP option of SYN packet

	/*
	 * Parameters which derived from TCP header and connection tracking
	 */
	UINT32 ref_ack;			// reference ack# used to calcualte relative ack#
	UINT32 rel_ack;			// relative ack# calculated from ref_ack
	INT32 ss_countdown;   	// The number of ack packets we should not reduce for slow start
	UINT32 sent_ack;		// the last ack# we ever sent to air
	UINT32 next_seq;		// {seq# of DATA packet} + {data length of DATA packet}, used to calculate BIF.
	UINT32 ref_seq;			// reference seq# used to calculate relative seq#
	UINT32 rel_seq;			// relative seq#
	UINT8 state;			// Connection state, INIT/SS/REDUCTION/CONGESTION
	ULONG last_tstamp;		// The timestamp of last incoming ACK which is declared as a reduction candidate
	ULONG fin_tstamp;		// The timestamp of last received ACK with FIN flag.

	/*
	 * Statistics which is used for reduction decision
	 */		
	UINT32 consecutive_data;	// consecutive TCP DATA count, reset while ACK received
	UINT32 consecutive_ack;		// consecutive TCP ACK count, reset while data received
	UINT32 consecutive_drop;	// consecutive TCP ACK which is dropped by us.
	UINT32 bif;					// Bytes In Flight, calculated based on our connection tracking info
	UINT32 pushack;				// the expected ack# of data segment with PSH flag
	UINT32 wsize_changed;       // the flag to indicate window size changed
	UINT32 avg_bif;             // the average of local max BIF
	UINT32 max_bif;             // max. BIF we ever calculated
	UINT32 ack_ratio;           // calculated ACK ratio before REDUCTION state

	/*
	 * Statistics which is used for debugging
	 */
	struct {
		UINT32 dropped;					// total ACK packets dropped by us
		UINT32 total;					// total ACK packets received by us
		UINT32 total_data;				// total DATA packets received by us		
		UINT32 timeout;					// total ACK packets which are dropped but timeout
		UINT32 retrans;					// total DATA packets which are detected as retransmission
		UINT32 dupack;					// total duplicate ACKs detected by us
		UINT32 rwnd_full;				// total number of times which we detect receive window full
		UINT32 max_consecutive_data;	// the max number of consecutive DATA packets
		UINT32 max_consecutive_ack;		// the max number of consecutive ACK packets
		UINT32 pass_state;				// the number of ACK which is ignored reduction because state is not STATE_REDUCTION
		UINT32 pass_con_drop;			// the number of ACK which is ignored reduction because exceed MAX_CONSECUTIVE_DROP_CNT
		UINT32 pass_con_data;     		// the number of ACK which is ignored reduction because exceed MAX_CONSECUTIVE_DATA_CNT
		UINT32 pass_win_warning;  		// the number of ACK which is ignored reduction because of receive window warnning
		UINT32 pass_sack;               // the number of ACK which is ignored reduction because of SACK included
		UINT32 pass_push_data;			// the number of ACK which is ignored reduction because of DATA with PSH flag
		UINT32 pass_push_data3;
		UINT32 pass_bif_warning;        // the number of ACK which is ignored reduction because of approaching avg_bif
		UINT32 pass_ack_ratio;          // the number of ACK which is ignored reduction because of exceed MAX_ACK_RATIO
		UINT32 pass_wsize_change;       // the number of ACK which is ignored reduction because of window size changed
		UINT32 drop_prob;				// the number of ACK which is dropped because of consecutve ACKs
		UINT32 data_jump;				// the number of DATA which seq# is not equal to next_seq
		UINT32 oldack;					// the number of ACK which ack# is less than last ack# we ever received
		UINT32 timeout_acks[10];        // the ack# which is timeout and flushed by RACK engine
	}stats;

	/*
	 * MISC
	 */
#if REDUCE_ACK_PKT_CACHE 
	struct {
		PNDIS_PACKET raw_pkt;
		rack_packet rack;
	}cache;
#endif //REDUCE_ACK_PKT_CACHE

	struct hlist_node	hnode;
	struct list_head 	list;
}rack_cnx;

// External APIs
BOOLEAN ReduceTcpAck(RTMP_ADAPTER* pAd, PNDIS_PACKET pPacket);//For TX ACK reduction
BOOLEAN ReduceAckUpdateDataCnx(RTMP_ADAPTER* pAd, PNDIS_PACKET pPacket); // For RX Data statistics update
VOID ReduceAckInit(RTMP_ADAPTER* pAd);
VOID ReduceAckExit(RTMP_ADAPTER* pAd);
VOID ReduceAckShow(RTMP_ADAPTER* pAd);
VOID ReduceAckSetEnable(RTMP_ADAPTER* pAd, UINT32 enable);
VOID ReduceAckSetProbability(RTMP_ADAPTER* pAd, UINT32 prob);

#endif /* __REDUCE_TCPACK_H__ */
